package com.sports.service.impl;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sports.common.convertor.SportsReqDtoConvertor;
import com.sports.common.convertor.SportsResDtoConvertor;
import com.sports.domain.dto.req.SportsReqDto;
import com.sports.domain.dto.res.SportsResDto;
import com.sports.domain.po.FavoritesPo;
import com.sports.domain.po.SportsPo;
import com.sports.mapper.FavoritesMapper;
import com.sports.mapper.SportsMapper;
import com.sports.service.SportsService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.CaseFormat;
import com.sports.common.exception.AppException;
import com.sports.common.exception.ErrorCode;
import com.baomidou.mybatisplus.ext.BasePService;
import com.baomidou.mybatisplus.ext.IPService;
import com.baomidou.mybatisplus.ext.Pager;
import com.baomidou.mybatisplus.ext.QueryParamUtils;
import com.sports.service.TokenService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@Slf4j
@Service("sportsAppService")
@Transactional(rollbackFor = Exception.class)
public class SportsServiceImpl implements SportsService {

    @Autowired
    private SportsReqDtoConvertor sportsReqDtoConvertor;

    @Autowired
    private SportsResDtoConvertor sportsResDtoConvertor;

    @Autowired
    private SportsMapper sportsMapper;

    @Autowired
    private FavoritesMapper favoritesMapper;

    @Autowired
    private TokenService tokenService;

    private IPService<SportsPo> sportsPoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public SportsServiceImpl(SportsMapper sportsMapper) {
        this.sportsPoService = new BasePService(sportsMapper);
    }


    @Override
    public SportsResDto save(SportsReqDto reqDto) {
        SportsPo po = sportsReqDtoConvertor.dto2Po(reqDto);
        sportsPoService.save(po);
        SportsResDto resDto = sportsResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public List<SportsResDto> getList() {
        List<SportsPo> list = sportsPoService.list();
        return sportsResDtoConvertor.poList2DtoList(list);
    }

    @Override
    public boolean deleteByIds(String ids) {
        try {
        List<Long> idLongList =
        Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
        return sportsPoService.removeByIds(idLongList);
        } catch (Exception e) {
        throw new AppException("参数错误：" + ids, ErrorCode.sys("417"), e);
        }
     }

    @Override
    public Pager<SportsResDto> doPager(Map<String, Object> params) {
        Pager<SportsPo> poPager = sportsPoService.queryPage(params, SportsPo.class);
        Pager<SportsResDto> resDtoPager = sportsResDtoConvertor.convertPoPager2ResDtoPager(poPager);
        return resDtoPager;
    }

    @Override
    public Pager<SportsResDto> page(SportsReqDto reqDto) {
        Integer currentPage = null == reqDto.getCurrentPage() ? 1 : reqDto.getCurrentPage();
        Integer pageSize = null ==  reqDto.getPageSize() ? 1 : reqDto.getPageSize();

        Page<SportsResDto> page = PageHelper.startPage(currentPage, pageSize);
        List<SportsPo> sportsPos = sportsMapper.pageList(reqDto);
        List<SportsResDto> sportsResDtos = sportsResDtoConvertor.poList2DtoList(sportsPos);
        Pager<SportsResDto> resDtoPager = new Pager<>();
        resDtoPager.setList(sportsResDtos);
        resDtoPager.setTotalCount(page.getTotal());
        resDtoPager.setCurrentPage(currentPage);
        resDtoPager.setPageSize(pageSize);

        for (SportsResDto sportsResDto : resDtoPager.getList()) {
            if (null != sportsResDto.getId()) {
                Integer favoritesTypeOne = favoritesMapper.selectCount(Wrappers.<FavoritesPo>lambdaQuery()
                        .eq(FavoritesPo::getSportsId, sportsResDto.getId())
                        .eq(FavoritesPo::getType, 1));
                Integer favoritesTypeTwo = favoritesMapper.selectCount(Wrappers.<FavoritesPo>lambdaQuery()
                        .eq(FavoritesPo::getSportsId, sportsResDto.getId())
                        .eq(FavoritesPo::getType, 2));
                sportsResDto.setFavoritesTypeOne(favoritesTypeOne);
                sportsResDto.setFavoritesTypeTwo(favoritesTypeTwo);
            }
        }

        return resDtoPager;
    }

    @Override
    public SportsResDto selectOne(Long id) {
        SportsPo po = sportsPoService.getById(id);
        SportsResDto resDto = sportsResDtoConvertor.po2Dto(po);
        Long userId = tokenService.getUserId();
        if (null != userId && null != resDto.getUserId()) {
            Integer favoritesTypeOne = favoritesMapper.selectCount(Wrappers.<FavoritesPo>lambdaQuery().eq(FavoritesPo::getUserId, userId)
                    .eq(FavoritesPo::getSportsId, resDto.getId()).eq(FavoritesPo::getType, 1));
            Integer favoritesTypeTwo = favoritesMapper.selectCount(Wrappers.<FavoritesPo>lambdaQuery().eq(FavoritesPo::getUserId, userId)
                    .eq(FavoritesPo::getSportsId, resDto.getId()).eq(FavoritesPo::getType, 2));
            resDto.setFavoritesTypeOne(favoritesTypeOne);
            resDto.setFavoritesTypeTwo(favoritesTypeTwo);
        }
        return resDto;
    }

    @Override
    public SportsResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(SportsPo::new, params);
        SportsPo po = sportsPoService.getOne(queryWrapper);
        SportsResDto resDto = sportsResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean updateProps(Long id, Map<String, Object> params) {
        UpdateWrapper<SportsPo> updateWrapper = QueryParamUtils.updateWrapper4Map(SportsPo::new, id, params);
        return sportsPoService.update(new SportsPo(), updateWrapper);
        }

    @Override
    public boolean updateProps(Long id, SportsReqDto reqDto) {
        SportsPo po = sportsReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);
        return sportsPoService.updateById(po);
    }


    @Override
    public boolean updateAllProps(Long id, SportsReqDto reqDto) {
        UpdateWrapper<SportsPo> updateWrapper = Wrappers.update();
        updateWrapper.eq("id", id);
        Field[] fields = SportsReqDto.class.getDeclaredFields();
        Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).forEach(field -> {
        try {
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), SportsReqDto.class);
        Method getMethod = propertyDescriptor.getReadMethod();
        String fileNameCamel = getMethod.getName().substring(3);
        String fileNameUnderline = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fileNameCamel);
        updateWrapper.set(fileNameUnderline, getMethod.invoke(reqDto));
        } catch (Exception ex) {
        log.warn("属性不存在get方法："+field.getName(),ex);
        }
        });
        return sportsPoService.update(new SportsPo(), updateWrapper);
    }

}